# -*- coding: utf-8 -*-
from Observer import Observer
from Exceptions.PlayerException import PlayerException
from MediaCollection.Audio.Track import Track
from Player.AudioPlayer import AudioPlayer

"""
Eine Klasse zur Verwaltung von Playlisten. Hinzugefügte Elemente müssen Objekte 
der Klasse Track sein. Diese werden der Reihe nach abgespielt. Über C(next()) 
kann der nächste Track gewählt werden, über C(previous()) der vorherige, über 
C(start()) die Wiedergabe gestartet und über C(stop()) gestoppt werden.
Die Klasse ist als Observer implementiert und kann so über das Stoppen der 
Wiedergabe vom eigentlichen Player benachrichtigt werden.

@author: Philipp Dermitzel
@date: 2011-03-31
@version: 1.0.2
"""
class Playlist(Observer):
    
    """
    ----------------------------------------------------------------------------
    Konstruktor
    ----------------------------------------------------------------------------
    """
    
    """
    Der  Konstruktor. 
    """
    def __init__(self): 
        """
        Die Playlist. In ihr werden Track-Objekte gespeichert, die nacheinander 
        abgespielt werden.
        @type: Array
        """
        self.__playlist = []
    
        """
        Der Cursor zeigt auf das gerade abgespielte Lied und somit das 
        Track-Objekt im Array.
        @type: int
        """
        self.__cursor = 0
    
        """
        Der Player.
        @type: AudioPlayer
        """
        self.__player = None
        
    """
    ----------------------------------------------------------------------------
    Getter und Setter
    ----------------------------------------------------------------------------
    """
    
    """
    Liefert die aktuelle Playlist mit den darin gespeicherten Track-Objekten.
    @return: Die aktuelle Playlist.
    @rtype: Array
    """
    def getPlaylist(self):
        return self.__playlist
        
    """
    Liefert die Position des Cursors im Playlist-Array.
    @return: Die Position des Cursors.
    @rtype: int
    """
    def getCursor(self):
        return self.__cursor
    
    """
    Setzt den Cursor auf eine gegebene Position im Playlist-Array.    
    @param position: Die Position im Array.
    @type position: int
    """
    def setCursor(self, position):
        if isinstance(position, int) and position < len(self.__playlist):
            self.__cursor = position
        else: raise PlayerException("""%s ist eine fehlerhafte Position in der 
            Playlist""" %(position))
        
    """
    ----------------------------------------------------------------------------
    Methoden der Klasse
    ----------------------------------------------------------------------------
    """
    
    """
    Fuegt der Playlist einen Track hinzu. Wirft PlayerExceptions!
    @param track: Der Track, der der Playlist hinzugefügt werden soll.
    @type track: Track
    """
    def add(self, track):
        if isinstance(track, Track) and track.getPath() is not None: 
            self.__playlist.append(track)
        else: raise PlayerException("""Es wurde kein gültiges Track-Objekt 
            übergeben""")
    
    """
    Beginnt das Abspielen der Playlist. Die Startposition kann als Parameter
    übergeben werden. Wirft PlayerExceptions!
    @param position: Die Position des Track-Objektes, mit welchem das Abspielen
        gestartet werden soll.
    @type position: int
    """    
    def start(self, position = 0):
        if len(self.__playlist) > 0:
            self.setCursor(position)
            self.__player = AudioPlayer(self.__playlist[self.__cursor]
                .getPath())
            self.__player.addObserver(self)
            self.__player.play()
        else: raise PlayerException("Die Playlist ist leer")
    
    """
    Spielt den nächsten Track in der Playlist. Stoppt die Wiedergabe falls keine
    weiteren Tracks mehr abzuspielen sind.
    """    
    def next(self):
        if self.__cursor < (len(self.__playlist) - 1):
            self.start(position=(self.__cursor + 1))
        else: self.stop()
    
    """
    Stoppt die Wiedergabe der Playlist. Die letzte Position wird nicht zurück-
    gesetzt, so dass das Abspielen wieder aufgenommen werden kann.
    """
    def stop(self):
        self.__player.stop()
    
    """
    Spielt den nächsten Track wenn der Observer (= die Playlist) vom Player
    die Nachricht erhält, dass der gerade abgespielte Track zuende ist.
    @param obj: Das Observable-Objekt. Wird in diesem Falle nicht benötigt.
    @type obj: unknown [Observable]
    """    
    def updateObserver(self, obj):
        self.next()
